package com.tanhua.gateway.filters;

import com.alibaba.fastjson.JSON;
import com.tanhua.commons.utils.JwtUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 自定义网关过滤器
 *   1、实现接口
 *   2、实现2个方法
 *   3、交给容器管理
 *   4、过滤器的核心方法filter
 */
@Component
public class AuthFilter implements GlobalFilter, Ordered {

    //存放所有不需要验证的url,自动根据“，”分割为数组
    @Value("${gateway.excludedUrls}")
    private List<String> excludeUrls;

    /**
     * 核心过滤方法
     *  exchange：请求上下文对象（获取request，response）
     *  chain：过滤器链
     */
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //1、判断当前的请求连接，是否需要验证
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getURI().getPath();  //请求连接  /login
        if(excludeUrls.contains(path)) {
            //2、如果不需要验证，放行。
            return chain.filter(exchange);
        }
        //3、如果需要验证，获取请求头中的 Authorization
        String token = request.getHeaders().getFirst("Authorization");
        if(!StringUtils.isEmpty(token)) {  //针对页面端发送的token前缀 “Bearer ”处理
            token = token.replaceAll("Bearer ","");
        }
        //4、调用JwtUtils的方法，验证
        boolean verifyToken = JwtUtils.verifyToken(token);  //true:正常，false：异常
        //5、如果验证通过返回true，放行
        if(verifyToken) {
            return chain.filter(exchange);
        }
        //6、如果验证失败，响应401并返回
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        //return response.setComplete();
        //返回一个500，返回401。需要响应Json字符串 {“”:"","":""}
        Map<String,Object> map = new HashMap<>();
        map.put("errCode", 401);
        map.put("errMessage", "用户未登录");
        //设置相应数据格式
        response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        byte[] data = JSON.toJSONBytes(map);
        DataBuffer buffer = response.bufferFactory().wrap(data); //数据DatBuffer
        return response.writeWith(Mono.just(buffer));
    }

    /**
     * 配置过滤器的执行顺序
     *    值越大，执行顺序越低
     */
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }
}
